import { gameController, RowColData } from "./gameController";
import BaseComp from "./ui/baseComp";
import { debugLog, deepClone } from "./utils/util";

const {ccclass, property} = cc._decorator;

export enum ShapeType {
    I = 'I',
    J = 'J',
    L = 'L',
    O = 'O',
    S = 'S',
    T = 'T',
    Z = 'Z'
}
@ccclass
export default abstract class Shape extends BaseComp {

    public shapeType: ShapeType = ShapeType.I;

    /** 每个子节点（在地图里面的）对应的行列信息 */
    private sonsInMap: {[key: string]: RowColData} = {};
    private isStop: boolean = false;

    private _angle: number = 0;
    public isRotating: boolean = false;

    /** 消除之后导致的形状下落 */
    public cleanAfterDown: boolean = false;

    public set angle(angle: number) {
        this._angle = angle;
        if(this._angle === -360) {
            angle = 0;
        }
        this.node.angle = angle;
    }

    public get angle(): number {
        return this._angle;
    }

    public setSonsInMap(key: string,value: RowColData) {
        this.sonsInMap[key] = value;
    }
    public getSonsInMap(key: string): RowColData {
        return this.sonsInMap[key];
    }
    
    onLoad(): void {
        debugLog('myName is ',this.shapeType);
    }

    public rotate(): void {
        if(this.shapeType === ShapeType.O) return;
        if(this.isStop) return;
        if(!this.canOptionShape()) return;
        this.angle -= 90;
        this.isRotating = true;
        const isValid = this.checkIsValidMap(() => {
            this.angle += 90;
            this.isRotating = false;
            console.log('=rotateMap ',gameController.stopedNodeMap);
        },'rotate');
        if(!isValid) return;
        

        const sons = this.node.children;
        const len = sons.length;
        for(let i = 0; i < len; i++) {
            const itemNode = sons[i];
            const minYNodeWorldPos = itemNode.parent.convertToWorldSpaceAR(itemNode.getPosition());
            const minYNodeMapLocalPos = gameController.shapeManager.mapRoot.convertToNodeSpaceAR(minYNodeWorldPos);
    
            const rowColObj = gameController.getRowByPoint(minYNodeMapLocalPos);
            console.log('==>rowColObj is ',rowColObj);
            // 获取行列
            const mapLocalPos = gameController.getMapLocalPos(rowColObj.row,rowColObj.col);
            const worldPos = gameController.game.viewMap['map'].convertToWorldSpaceAR(mapLocalPos);
            const rightLocalPos = this.node.convertToNodeSpaceAR(worldPos);
            // rightLocalPos.x = Math.round(rightLocalPos.x);
            // rightLocalPos.y = Math.round(rightLocalPos.y);

            itemNode.setPosition(rightLocalPos);

            // 更新地图
            const {row,col} = this.sonsInMap[itemNode.uuid];
            if(!gameController.isInMapWithRowColObj(this.sonsInMap[itemNode.uuid])) continue;

            gameController.gameMap[row][col] = null;
            gameController.stopedNodeMap[row][col] = 0;

            const [rightRow,rightCol] = [rowColObj.row,rowColObj.col];
            if(!gameController.isInMapWithRowColObj(rowColObj)) continue;
            
            gameController.gameMap[rightRow][rightCol] = itemNode;
            gameController.stopedNodeMap[rightRow][rightCol] = 1;
            this.sonsInMap[itemNode.uuid] = rowColObj;
            itemNode['row'] = rightRow;
            itemNode['col'] = rightCol;

        }
        console.log("===========================");
        this.isRotating = false;
    }

    /** 是否可以操作该形状 */
    public canOptionShape(): boolean {
        return this.node.children.every(item => {
            const itemNodeWorldPos = item.parent.convertToWorldSpaceAR(item.getPosition());
            const itemNodeMapLocalPos = gameController.shapeManager.mapRoot.convertToNodeSpaceAR(itemNodeWorldPos);
            const rowColObj = gameController.getRowByPoint(itemNodeMapLocalPos);
            if(rowColObj.row >= 1) {
                return true;
            }
            return false;
        })
    }

    public checkIsValidMap(callback: Function,tag: string): boolean {
        const sons = this.node.children;
        const len = sons.length;
        const falseFunc = (reason: string) => {
            console.log(reason);     
            // 不能旋转就将原来的角度加回来
            callback();
            return false;
        }
        let allNodeIsOut = false;
        // 存在小于零行的节点证明刚刚出生允许下落      
        allNodeIsOut = sons.some(item => {
            const rowColObj = this.sonsInMap[item.uuid];
            if(rowColObj.row <= 0) {
                return true;
            }
            return false;
        });
        if(allNodeIsOut) return true;

        for(let i = 0; i < len; i++) {
            const itemNode = sons[i];
            // 深复制一个行列对象目的是不影响原来的对象
            const tempRowColObj = deepClone(this.sonsInMap[itemNode.uuid]);
            if(!gameController.isInMapWithRowColObj(tempRowColObj)) return false;
            let rotateRowColObj: RowColData = null;
        
            let isInMap = true;
            switch(tag) {
                case 'left':
                    tempRowColObj.col--;
                    isInMap = gameController.isInMapWithRowColObj(tempRowColObj);
                    break;
                case 'right':
                    tempRowColObj.col++;
                    isInMap = gameController.isInMapWithRowColObj(tempRowColObj);
                    break;
                case 'down':
                    tempRowColObj.row++;
                    isInMap = gameController.isInMapWithRowColObj(tempRowColObj);
                    break;
                case 'rotate':
                    const minYNodeWorldPos = itemNode.parent.convertToWorldSpaceAR(itemNode.getPosition());
                    const minYNodeMapLocalPos = gameController.shapeManager.mapRoot.convertToNodeSpaceAR(minYNodeWorldPos);
            
                    rotateRowColObj = gameController.getRowByPoint(minYNodeMapLocalPos);
                    isInMap = gameController.isInMapWithRowColObj(rotateRowColObj);
                    break;
                default:
                    break;        
            }
            if(!isInMap) {
                return falseFunc(tag + ' 超出边界了');
            }
            const {row,col} = tempRowColObj;
            const gridNode = gameController.gameMap[row][col];
            
            if(gridNode && gridNode.parent !== this.node) return falseFunc(tag + '对应位置有节点了');  
            if(rotateRowColObj) {
                const [rotateRow,rotateCol] = [rotateRowColObj.row,rotateRowColObj.col];
                const rotateGridNode = gameController.gameMap[rotateRow][rotateCol];

                // 如果目标位置有节点直接返回false
                if(rotateGridNode && rotateGridNode.parent !== this.node) return falseFunc(tag + "对应的位置已经有其他的形状节点了");

                // 是否能旋转取决于旋转节点的左边和目标位置的下边是否有节点（旋转中心下的所有节点）和右边是否有节点（旋转中心上方的所有节点）
                if(rotateCol < tempRowColObj.col && gameController.isInMapWithRowColObj({row: tempRowColObj.row,col: tempRowColObj.col - 1})) {
                    const tNode = gameController.gameMap[tempRowColObj.row][tempRowColObj.col - 1];
                    if(tNode && tNode.parent !== this.node) {
                        return falseFunc(tag + ' 向左旋转的时候旋转节点的左边有节点挡住了');
                    }
                } 

                if(rotateCol < tempRowColObj.col && gameController.isInMapWithRowColObj({row: rotateRow - 1,col: rotateCol})) {
                    const tNode = gameController.gameMap[rotateRow - 1][rotateCol];
                    if(tNode && tNode.parent !== this.node) {
                        return falseFunc(tag + ' 向左旋转的时候目标位置下面有节点挡住了');
                    }
                }

                if(rotateCol > tempRowColObj.col && gameController.isInMapWithRowColObj({row: tempRowColObj.row,col: tempRowColObj.col + 1})) {
                    const tNode = gameController.gameMap[tempRowColObj.row][tempRowColObj.col + 1];
                    if(tNode && tNode.parent !== this.node) {
                        return falseFunc(tag + ' 向右顺时针旋转的时候右边有个节点挡住了');
                    }
                }
                
            }
        }
        return true;
    }

    public goDown(): void {
        if(this.isStop) return;
        if(this.isRotating) return;
        this.node.y -= 32;
        const isValid = this.checkIsValidMap(() => {
            console.log(this.shapeType);
            gameController.game.hasAccelate = false;
            gameController.game.downSpeed = 0.3;

            this.node.y += 32; 

            gameController.game.curGoDownShape = null;
            gameController.game.curGoDownShape = gameController.shapeManager.prepareNextShape();
            gameController.shapeManager.checkClear();
        },'down');
        if(isValid) {
            // 可以下落更新地图
            this.updateMap('down');
        }
    }

    /**
     * 检查所有子节点是否存在跟地图上的格子重合的点, 旋转过程中可能计算有误 重点查这部分代码的bug
     * @returns boolean
     */
    public updateMap(tag: 'left' | 'right' | 'down'): void {
        const oldSonsMap = this.sonsInMap;
        // 清除掉所有的旧数据
        this.node.children.forEach(item => {
            // 赋值新的数据
            const rowColObj = oldSonsMap[item.uuid];
            if(gameController.isInMapWithRowColObj(rowColObj)) {
                gameController.gameMap[rowColObj.row][rowColObj.col] = null;
                gameController.stopedNodeMap[rowColObj.row][rowColObj.col] = 0;
            }
        });

        const changeWithTag = () => {
            {
                this.node.children.forEach(item => {
                    const uuid = item.uuid;
                    const oldRowColObj = this.sonsInMap[uuid];
                    switch(tag) {
                        case "left":
                            this.sonsInMap[uuid].col = oldRowColObj.col - 1;
                            break;
                        case "right":
                            this.sonsInMap[uuid].col = oldRowColObj.col + 1;
                            break;
                        case "down": 
                            this.sonsInMap[uuid].row = oldRowColObj.row + 1;
                            break
                        default:
                            break;
                    }
                    
                    const newRow = this.sonsInMap[uuid].row;
                    const newCol = this.sonsInMap[uuid].col;
                    if(!gameController.isInMapWithRowColObj(this.sonsInMap[uuid])) return;

                    gameController.gameMap[newRow][newCol] = item;
                    gameController.stopedNodeMap[newRow][newCol] = 1;
                    item['row'] = newRow;
                    item['col'] = newCol;
                })
            }
        }
        changeWithTag();
    }

    /** 消除的时候清除对应的数据 */
    public cleanUp(uuid: string): void {
        const rowColObj = this.sonsInMap[uuid];
        const {row,col} = rowColObj;
        gameController.gameMap[row][col] = null;
        gameController.stopedNodeMap[row][col] = 0;
    }

    public goLeft(): void {
        if(this.isStop) return;
        this.node.x -= 32;

        const isValid = this.checkIsValidMap(() => {
            this.node.x += 32;
        },'left');

        if(isValid) {
            this.updateMap('left');
        }
    }
    public goRight(): void {
        if(this.isStop) return;
        this.node.x += 32;
        const isValid = this.checkIsValidMap(() => {
            this.node.x -= 32;
        },'right');

        if(isValid) {
            this.updateMap('right');
        }
    }
}
